#include <sw/redis++/redis.h>
#include <iostream>

namespace mag {

    // Redis 客户端工厂类，用于创建 Redis 连接实例
    class RedisClientFactory {
        public:
            // 静态工厂方法，创建并返回 Redis 客户端对象
            // 参数：主机地址(host)，端口(port)，数据库索引(db)，是否保持连接(keep_alive)
            static std::shared_ptr<sw::redis::Redis> create(
                const std::string &host,    // Redis 服务器地址
                int port,                   // Redis 服务器端口
                int db,                     // Redis 数据库索引
                bool keep_alive)            // 是否保持连接
            {
                // 配置 Redis 连接选项
                sw::redis::ConnectionOptions opts;
                opts.host = host;
                opts.port = port;
                opts.db = db;
                opts.keep_alive = keep_alive;
                
                // 返回创建的 Redis 客户端实例
                auto res = std::make_shared<sw::redis::Redis>(opts);
                return res;
            }
    };

    // 会话管理类，用于管理用户会话信息(会话ID : 用户ID)
    class Session {
        public:
            using ptr = std::shared_ptr<Session>;

            // 构造函数，接受 Redis 客户端实例
            Session(const std::shared_ptr<sw::redis::Redis> &redis_client)
                : _redis_client(redis_client) {}

            // 向 Redis 中添加会话信息，使用 SSID 作为键，UID 作为值
            void append(const std::string &ssid, const std::string &uid) {
                _redis_client->set(ssid, uid);  // 设置键值对
            }

            // 从 Redis 中删除会话信息，删除指定 SSID 的键
            void remove(const std::string &ssid) {
                _redis_client->del(ssid);  // 删除指定键
            }

            // 获取会话信息，根据 SSID 获取对应的 UID
            sw::redis::OptionalString uid(const std::string &ssid) {
                return _redis_client->get(ssid);  // 获取键的值
            }

        private:
            std::shared_ptr<sw::redis::Redis> _redis_client;  // Redis 客户端实例
    };

    // 用户状态管理类，用于管理用户的在线状态（用户ID：空值）
    class Status {
        public:
            using ptr = std::shared_ptr<Status>;

            // 构造函数，接受 Redis 客户端实例
            Status(const std::shared_ptr<sw::redis::Redis> &redis_client)
                : _redis_client(redis_client) {}

            // 向 Redis 中添加用户的在线状态，使用 UID 作为键，空字符串作为值
            void append(const std::string &uid) {
                _redis_client->set(uid, "");  // 设置键值对
            }

            // 从 Redis 中删除用户的在线状态，删除指定 UID 的键
            void remove(const std::string &uid) {
                _redis_client->del(uid);  // 删除指定键
            }

            // 检查用户是否在线，判断指定 UID 是否存在
            bool exists(const std::string &uid) {
                auto res = _redis_client->get(uid);  // 获取键的值
                return res.has_value();  // 如果键存在，返回 true
            }

        private:
            std::shared_ptr<sw::redis::Redis> _redis_client;  // Redis 客户端实例
    };

    // 验证码管理类，用于管理验证码的存储和过期（验证码ID：验证码）
    class Codes {
        public:
            using ptr = std::shared_ptr<Codes>;

            // 构造函数，接受 Redis 客户端实例
            Codes(const std::shared_ptr<sw::redis::Redis> &redis_client)
                : _redis_client(redis_client) {}

            // 向 Redis 中添加验证码，使用 CID 作为键，验证码作为值
            // 参数 t 为验证码的过期时间，默认为 5 分钟
            void append(const std::string &cid, const std::string &code, 
                const std::chrono::milliseconds &t = std::chrono::milliseconds(300000)) {
                _redis_client->set(cid, code, t);  // 设置键值对，并指定过期时间
            }

            // 从 Redis 中删除验证码，删除指定 CID 的键
            void remove(const std::string &cid) {
                _redis_client->del(cid);  // 删除指定键
            }

            // 获取验证码，根据 CID 获取对应的验证码值
            sw::redis::OptionalString code(const std::string &cid) {
                return _redis_client->get(cid);  // 获取键的值
            }

        private:
            std::shared_ptr<sw::redis::Redis> _redis_client;  // Redis 客户端实例
    };
}
